package cn.com.libertymutual.sp.service.impl;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.text.ParseException;
import java.util.HashMap;
import java.util.Random;

import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import com.google.common.collect.Maps;

import cn.com.libertymutual.core.redis.util.RedisUtils;
import cn.com.libertymutual.core.util.Constants;
import cn.com.libertymutual.core.util.DateUtil;
import cn.com.libertymutual.core.web.ServiceResult;
import cn.com.libertymutual.sp.service.api.CaptchaService;

/**
 * @author AoYi
 *
 */
@Service("CaptchaService")
public class CaptchaServiceImpl implements CaptchaService {
	private Logger log = LoggerFactory.getLogger(getClass());

	/* 随机字符字典 */
	private static final char[] CHARS = { '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N',
			'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z' };

	/* 随机数 */
	private static Random random = new Random();
	private static int width = 80;// 验证码图片 宽
	private static int height = 30;// 高
	private static int randomsize = 4; // 随机数长度

	@Override
	public void outputCaptcha(HttpServletRequest request, HttpServletResponse response, RedisUtils redis) throws ServletException, IOException {
		response.setContentType("image/jpeg");

		String randomString = getRandomString();
		// 存储到缓存
		HashMap<String, String> captcha = Maps.newHashMap();
		captcha.put("code", randomString);
		captcha.put("time", DateUtil.getStringDate2());// yyyy-mm-dd hh:mm:ss.sss

		this.drawCode(response, randomString);// 输出图片
		// 指定时间缓存图形码
		redis.set(request.getSession().getId(), Constants.REDIS_IMG_VERIFY_CODE, captcha);
		log.info("new_imgCode==>{}", captcha);
	}

	/**Remarks: 输出指定字符串的图片<br>
	 * Version：1.0<br>
	 * Author：AoYi<br>
	 * DateTime：2017年11月14日上午10:15:49<br>
	 * Project：liberty_sale_plat<br>
	 * @param response
	 * @param randomString
	 * @throws IOException
	 */
	private void drawCode(HttpServletResponse response, String randomString) throws IOException {
		BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
		Graphics2D g = bi.createGraphics();
		g.setFont(new Font(Font.SANS_SERIF, Font.BOLD, 16));
		g.setColor(getRandColor(200, 250));// 背景色
		g.fillRect(0, 0, width, height);
		Color reverse = getReverseColor(getRandColor(200, 255));
		g.setColor(reverse);// 文字颜色
		g.drawString(randomString, 18, 20);
		// 随机产生干扰线
		g.setColor(getRandColor(160, 200));// 干扰线颜色
		for (int i = 0; i < 20; i++) {
			int x = random.nextInt(width);
			int y = random.nextInt(height);
			int xl = random.nextInt(25);
			int yl = random.nextInt(30);
			// 从A点画到B点
			g.drawLine(x, y, x + xl, y + yl);
		}
		// 转成JPEG格式
		ServletOutputStream out = response.getOutputStream();

		ImageIO.write(bi, "jpg", out);
		out.close();
		bi.flush();

		/*
		 * JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
		 * encoder.encode(bi); out.flush();
		 */
	}

	/**
	 * Remarks: 获取4位随机<br>
	 * Version：1.0<br>
	 * Author：AoYi<br>
	 * DateTime：2017年12月21日下午3:19:53<br>
	 * Project：liberty_sale_plat<br>
	 * @return
	 */
	private static String getRandomString() {
		StringBuffer buffer = new StringBuffer();
		for (int i = 0; i < randomsize; i++) {
			buffer.append(CHARS[random.nextInt(CHARS.length)]);
		}
		return buffer.toString();
	}

	/**
	 * Remarks: 给定范围获得随机颜色<br>
	 * Version：1.0<br>
	 * Author：AoYi<br>
	 * DateTime：2017年12月21日下午3:49:51<br>
	 * Project：liberty_sale_plat<br>
	 * @param fc
	 * @param bc
	 * @return
	 */
	private Color getRandColor(int fc, int bc) {
		Random random = new Random();
		if (fc > 255)
			fc = 255;
		if (bc > 255)
			bc = 255;
		int r = fc + random.nextInt(bc - fc);
		int g = fc + random.nextInt(bc - fc);
		int b = fc + random.nextInt(bc - fc);
		return new Color(r, g, b);
	}

	/**
	 * Remarks: 返回某颜色的反色<br>
	 * Version：1.0<br>
	 * Author：AoYi<br>
	 * DateTime：2017年12月21日下午3:19:38<br>
	 * Project：liberty_sale_plat<br>
	 * @param c
	 * @return
	 */
	private static Color getReverseColor(Color c) {
		return new Color(255 - c.getRed(), 255 - c.getGreen(), 255 - c.getBlue());
	}

	@Override
	public boolean validationCaptcha(HttpServletRequest request, ServiceResult sr, RedisUtils redis, String imgCode) throws ParseException {
		HashMap<String, Object> map = Maps.newHashMap();
		sr.setResult(Constants.SYS_ERROR_MSG);
		map.put("state", ServiceResult.STATE_EXCEPTION);
		if (StringUtils.isBlank(imgCode)) {
			sr.setResult("图形码为空");
			return false;
		}
		// 获取缓存中的验证码
		Object object = redis.get(request.getSession().getId(), Constants.REDIS_IMG_VERIFY_CODE);
		if (object == null) {
			sr.setResult("图形码过期,请重新获取");
			return false;
		}
		@SuppressWarnings("unchecked")
		HashMap<String, String> captcha = (HashMap<String, String>) object;
		String storeCode = captcha.get("code");
		String sendTime = captcha.get("time");
		// 验证码校验格式
		if (StringUtils.isBlank(storeCode) || storeCode.trim().length() != 4) {
			sr.setResult("图形码长度错误");
			return false;
		}
		// 验证码时间校验格式
		if (StringUtils.isBlank(sendTime) || !sendTime.trim().matches(Constants.REGEX_DATE_FORMART2)) {
			sr.setResult("图形码格式错误");
			return false;
		}
		// Long oldTime = new
		// SimpleDateFormat(DateUtil.DATE_TIME_PATTERN2LANG).parse(sendTime).getTime();
		// Long overTime = System.currentTimeMillis() - oldTime;// 剩余时间
		// // 验证码过期,1秒=1000毫秒
		// if (overTime >= Constants.KEY_IMG_VALIDATE_OUTTIME * 1000) {
		// sr.setResult("图形码超时");
		// return false;
		// }
		if (storeCode.trim().toUpperCase().equals(imgCode.trim().toUpperCase())) {
			sr.setResult("图形码正确");
			map.put("state", ServiceResult.STATE_SUCCESS);
			return true;
		}
		sr.setResult("图形码错误");
		return false;
	}
}